﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;

namespace Sharpie
{
    class Snake
    {
        public int EatCount { get; set; }
        public int Length { get; set; }
        public int MoveSpeed { get; set; }
        public Spawninfo SpawnInfo { get { return spawninfo; } }
        public int Score { get; set; }
        public bool IsAlive { get { return alive; } }
        public bool IsSpawned { get { return spawned; } }
        public LinkedList<Point> Segments { get { return segments; } }
        public Point NextHeadPos
        {
            get
            {
                
                return new Point(segments.First.Value.X + (int)move.X, segments.First.Value.Y + (int)move.Y);
            }
        }

        public string Name { get; set; }
        public Color BodyColor { get; set; }
        public Color DeadColor { get; set; }
        public Color CurrentColor
        {
            get
            {
                if (IsAlive) return BodyColor;
                else return DeadColor;
            }
        }

        public Map.Size mapSize;
        private bool alive = true;
        private bool spawned = false;
        private Direction prevdir;
        public Direction CrntDirection { get; set; }
        public Direction PrvDirection { get { return prevdir; } }
        private Vector2 move
        {
            get
            {
                Vector2 move = new Vector2();
                switch (CrntDirection)
                {
                    case Direction.Up:
                        move = new Vector2(0, -1);
                        break;

                    case Direction.Down:
                        move = new Vector2(0, 1);
                        break;

                    case Direction.Left:
                        move = new Vector2(-1, 0);
                        break;

                    case Direction.Right:
                        move = new Vector2(1, 0);
                        break;

                    case Direction.None:
                        move = new Vector2(0, 0);
                        break;
                }

                if (segments.First.Value.X + (int)move.X == mapSize.Width)
                    move.X = -mapSize.Width;
                if (segments.First.Value.X + (int)move.X < 0)
                    move.X = mapSize.Width;
                if (segments.First.Value.Y + (int)move.Y == mapSize.Height)
                    move.Y = -mapSize.Height;
                if (segments.First.Value.Y + (int)move.Y < 0)
                    move.Y = mapSize.Height;

                return move;
            }
        }
        private LinkedList<Point> segments = new LinkedList<Point>();

        private Spawninfo spawninfo;

        public Snake(int speed, int length, Color bodycolor, Point spawnpoint, Map.Size mapSize)
        {
            spawninfo = new Snake.Spawninfo(length, speed, spawnpoint);
            BodyColor = bodycolor;
            this.mapSize = mapSize;
            Spawn();
        }

        public enum Direction
        {
            Up,
            Down,
            Left,
            Right,
            None
        }

        public struct Spawninfo
        {
            public int Length, MoveSpeed;
            public Point Spawnpoint;

            public Spawninfo(int length, int movespeed, Point spawnpoint)
            {
                Length = length;
                MoveSpeed = movespeed;
                Spawnpoint = spawnpoint;
            }
        }

        private void Initialize()
        {
            Length = spawninfo.Length;
            MoveSpeed = spawninfo.MoveSpeed;
            alive = true;
            spawned = false;
            Segments.Clear();
        }

        private void ClearScore()
        {
            EatCount = 0;
            Score = 0;
        }

        public void Move()
        {
            prevdir = CrntDirection;

            if (segments.Contains(new Point((int)move.X, (int)move.Y)))
            {
                segments.Reverse();
            }
            else
            {
                segments.AddFirst(NextHeadPos);

                if (Length <= segments.Count - 1)
                {
                    int removeCount;
                    if (Length < segments.Count - 1) removeCount = 2;
                    else removeCount = 1;
                    for (int i = 0; i < removeCount; i++)
                    {
                        if (segments.Count > 2) segments.RemoveLast();
                    }
                }
            }
        }

        public void Kill()
        {
            alive = false;
        }

        public void Spawn()
        {
            Initialize();
            segments.AddFirst(spawninfo.Spawnpoint);
            spawned = true;
        }
    }
}
